package com.example.pages;

import com.example.model.SortedListOf;
import com.example.model.User;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import java.util.List;

import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent;

public class UsersPage extends InternalPage {

    @FindBy(name = "username")
    public WebElement usernameField;

    @FindBy(name = "email")
    public WebElement emailField;

    @FindBy(name = "password")
    public WebElement passwordField;

    @FindBy(name = "password2")
    public WebElement passwordConfirmationField;

    @FindBy(name = "submit")
    public WebElement saveButton;

    @FindBy(css = "div#user-list table > tbody > tr")
    public List<WebElement> userRows;

    @FindBy(xpath = "//*[@class='error'][@for='username']")
    public WebElement usernameError;

    @FindBy(xpath = "//*[@class='error'][@for='email']")
    public WebElement emailError;

    @FindBy(xpath = "//*[@class='error'][@for='password2']")
    public WebElement confirmationError;

    public UsersPage registerUser(User user) {
        usernameField.sendKeys(user.name);
        emailField.sendKeys(user.email);
        passwordField.sendKeys(user.password);
        passwordConfirmationField.sendKeys(user.passwordConfirmation);
        saveButton.click();
        return MyPageFactory.getPage(driver, UsersPage.class);

    }

    /**
     * Проверка ошибок при логине
     *
     * @param errorMessage ожидаемый текст сообщения
     * @param type         тип ошибки. 1-не заполнен логин 2-не валидный email 3-пароли не совпадают
     */
    public UsersPage checkErrorMessage(String errorMessage, int type) {
        switch (type) {
            case 1:
                Assert.assertTrue("Должно быть показано сообщение об ошибке", usernameError.isDisplayed());
                Assert.assertTrue("Сообщение об ошибке должно быть = " + errorMessage, usernameError.getText().contains(errorMessage));
                break;
            case 2:
                Assert.assertTrue("Должно быть показано сообщение об ошибке", emailError.isDisplayed());
                Assert.assertTrue("Сообщение об ошибке должно быть = " + errorMessage, emailError.getText().contains(errorMessage));
                break;
            case 3:
                Assert.assertTrue("Должно быть показано сообщение об ошибке", confirmationError.isDisplayed());
                Assert.assertTrue("Сообщение об ошибке должно быть = " + errorMessage, confirmationError.getText().contains(errorMessage));
                break;
        }
        return MyPageFactory.getPage(driver, UsersPage.class);
    }

    public UsersPage deleteUser(User user) {
        for (WebElement row : userRows) {
          if (user.equals(convertRowToUser(row))) {
            row.findElement(By.xpath("./td[6]/a")).click();
            wait_().until(alertIsPresent()).accept();
            break;
          }
        }
        cachedUsers = null;
        return MyPageFactory.getPage(driver, UsersPage.class);
    }

    private SortedListOf<User> cachedUsers;

    public SortedListOf<User> getUsers() {
        if (cachedUsers == null) {
            cachedUsers = new SortedListOf<User>();
            for (WebElement row : userRows) {
                cachedUsers.add(convertRowToUser(row));
            }
        }

        return new SortedListOf<User>(cachedUsers);
    }

    public int getUserCount() {
        return userRows.size();
    }

    private User convertRowToUser(WebElement row) {
        List<WebElement> cells = row.findElements(By.tagName("td"));
        return new User()
                .withName(cells.get(1).getText())
                .withEmail(cells.get(2).getText())
                .withRole(cells.get(3).getText());
    }

}
